﻿' ***********************************************************************
' Assembly         : Ioc
' Author           : Tim Ford
' Created          : 10-02-2013
'
' Last Modified By : Tim Ford
' Last Modified On : 10-02-2013
' ***********************************************************************
' <copyright file="HelperMethods.vb" company="Red Baron Solutions">
'     Red Baron Solutions. All rights reserved.
' </copyright>
' <summary></summary>
' ***********************************************************************
Imports System.Reflection

Public Module HelperMethods


    ''' <summary>
    ''' Determines whether [is primitive type] [the specified type].	
    ''' </summary>
    ''' <param name="type">The type.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.Runtime.CompilerServices.Extension> _
    Public Function IsPrimitiveType(type As Type) As Boolean
        If m_TypeDictionary Is Nothing Then
            m_TypeDictionary = New HashSet(Of Type)
            m_TypeDictionary.Add(GetType([String]))
            m_TypeDictionary.Add(GetType([Decimal]))
            m_TypeDictionary.Add(GetType(DateTime))
            m_TypeDictionary.Add(GetType(DateTimeOffset))
            m_TypeDictionary.Add(GetType(TimeSpan))
            m_TypeDictionary.Add(GetType(Guid))
        End If
        If type IsNot Nothing Then
            Return type.IsValueType OrElse type.IsPrimitive OrElse m_TypeDictionary.Contains(type) OrElse Convert.GetTypeCode(type) <> TypeCode.[Object]
        End If
        Return False
    End Function
    Private m_TypeDictionary As HashSet(Of Type)

    ''' <summary>
    ''' Determines whether the specified member has attribute.	
    ''' </summary>
    ''' <typeparam name="TAttribute">The type of the attribute.</typeparam>
    ''' <param name="member">The member.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function HasAttribute(Of TAttribute As Attribute)(member As MemberInfo) As Boolean
        Dim attributes = member.GetCustomAttributes(GetType(TAttribute), True)
        Return attributes.Length > 0
    End Function

    ''' <summary>
    ''' Determines whether the specified member has attribute.	
    ''' </summary>
    ''' <typeparam name="TAttribute">The type of the attribute.</typeparam>
    ''' <param name="member">The member.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.Runtime.CompilerServices.Extension()> _
    Public Function HasAttribute(Of TAttribute As Attribute)(member As PropertyInfo) As Boolean
        Dim attributes = member.GetCustomAttributes(GetType(TAttribute), True)
        Return attributes.Length > 0
    End Function

    <System.Runtime.CompilerServices.Extension()>
    Public Function GetAttribute(Of T As Attribute)(type As Type) As T
        Return CType(type.GetCustomAttributes(True).FirstOrDefault(Function(item)
                                                                       Return item.GetType Is GetType(T)
                                                                   End Function), T)
    End Function

    <System.Runtime.CompilerServices.Extension()>
    Public Function GetAttribute(Of T As Attribute)(type As MethodInfo) As T
        Return CType(type.GetCustomAttributes(True).FirstOrDefault(Function(item)
                                                                       Return item.GetType Is GetType(T)
                                                                   End Function), T)
    End Function


    <System.Runtime.CompilerServices.Extension()>
    Public Function GetAttribute(Of T As Attribute)(type As ParameterInfo) As T
        Return CType(type.GetCustomAttributes(True).FirstOrDefault(Function(item)
                                                                       Return item.GetType Is GetType(T)
                                                                   End Function), T)
    End Function


    ''' <summary>
    ''' 	Performs an action for each item in the enumerable
    ''' </summary>
    ''' <typeparam name = "T">The enumerable data type</typeparam>
    ''' <param name = "values">The data values.</param>
    ''' <param name = "action">The action to be performed.</param>
    ''' <example>
    ''' 	var values = new[] { "1", "2", "3" };
    ''' 	values.ConvertList&lt;string, int&gt;().ForEach(Console.WriteLine);
    ''' </example>
    ''' <remarks>
    ''' 	This method was intended to return the passed values to provide method chaining. However due to deferred execution the compiler would actually never run the entire code at all.
    ''' </remarks>
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub ForEach(Of T)(ByVal values As IEnumerable(Of T), ByVal action As Action(Of T))
        If action Is Nothing Then
            Throw New ArgumentNullException("Action Missing")
        End If
        For Each value As T In values.ToList
            action(value)
        Next
    End Sub

    <System.Runtime.CompilerServices.Extension()> _
    Friend Function GetCastingString(ByVal type As Type) As String
        Select Case type
            Case GetType(String)
                Return "CStr({0})"
            Case GetType(Int32)
                Return "CInt({0})"
            Case GetType(Int32?)
                Return "CInt({0})"
            Case GetType(Integer)
                Return "CInt({0})"
            Case GetType(Integer?)
                Return "CInt({0})"
            Case GetType(Int16)
                Return "CShort({0})"
            Case GetType(Int16?)
                Return "CShort({0})"
            Case GetType(Short)
                Return "CShort({0})"
            Case GetType(Short?)
                Return "CShort({0})"
            Case GetType(Int64)
                Return "CLng({0})"
            Case GetType(Int64?)
                Return "CLng({0})"
            Case GetType(Long)
                Return "CLng({0})"
            Case GetType(Long?)
                Return "CLng({0})"
            Case GetType(Date)
                Return "CDate({0})"
            Case GetType(Date?)
                Return "CDate({0})"
            Case GetType(DateTime)
                Return "CDate({0})"
            Case GetType(DateTime?)
                Return "CDate({0})"
            Case GetType(Decimal)
                Return "CDec({0})"
            Case GetType(Decimal?)
                Return "CDec({0})"
            Case GetType(Double)
                Return "CDbl({0})"
            Case GetType(Double?)
                Return "CDbl({0})"
            Case GetType(Single)
                Return "CSng({0})"
            Case GetType(Single?)
                Return "CSng({0})"
            Case GetType(Byte)
                Return "DirectCast({0}, Byte)"
            Case GetType(Byte?)
                Return "DirectCast({0}, Byte)"
            Case GetType(Byte())
                Return "DirectCast({0}, Byte())"
            Case GetType(Char)
                Return "CChar({0})"
            Case GetType(Char?)
                Return "CChar({0})"
            Case GetType(Boolean)
                Return "CBool({0})"
            Case GetType(Boolean?)
                Return "CBool({0})"
            Case GetType(UInt16)
                Return "CUShort({0})"
            Case GetType(UInt16?)
                Return "CUShort({0})"
            Case GetType(UInt32)
                Return "CUInt({0})"
            Case GetType(UInt32?)
                Return "CUInt({0})"
            Case GetType(UInt64)
                Return "CULng({0})"
            Case GetType(UInt64?)
                Return "CULng({0})"
            Case Else
                Return String.Format("DirectCast({{0}}, {0})", type.FullName)
        End Select
    End Function
End Module
